import { allowedMethods } from '../../../../src/server/auth/middleware/allowedMethods.js';
import express, { Request, Response } from 'express';
import request from 'supertest';

describe('allowedMethods', () => {
    let app: express.Express;

    beforeEach(() => {
        app = express();

        // Set up a test router with a GET handler and 405 middleware
        const router = express.Router();

        router.get('/test', (req, res) => {
            res.status(200).send('GET success');
        });

        // Add method not allowed middleware for all other methods
        router.all('/test', allowedMethods(['GET']));

        app.use(router);
    });

    test('allows specified HTTP method', async () => {
        const response = await request(app).get('/test');
        expect(response.status).toBe(200);
        expect(response.text).toBe('GET success');
    });

    test('returns 405 for unspecified HTTP methods', async () => {
        const methods = ['post', 'put', 'delete', 'patch'];

        for (const method of methods) {
            // @ts-expect-error - dynamic method call
            const response = await request(app)[method]('/test');
            expect(response.status).toBe(405);
            expect(response.body).toEqual({
                error: 'method_not_allowed',
                error_description: `The method ${method.toUpperCase()} is not allowed for this endpoint`
            });
        }
    });

    test('includes Allow header with specified methods', async () => {
        const response = await request(app).post('/test');
        expect(response.headers.allow).toBe('GET');
    });

    test('works with multiple allowed methods', async () => {
        const multiMethodApp = express();
        const router = express.Router();

        router.get('/multi', (req: Request, res: Response) => {
            res.status(200).send('GET');
        });
        router.post('/multi', (req: Request, res: Response) => {
            res.status(200).send('POST');
        });
        router.all('/multi', allowedMethods(['GET', 'POST']));

        multiMethodApp.use(router);

        // Allowed methods should work
        const getResponse = await request(multiMethodApp).get('/multi');
        expect(getResponse.status).toBe(200);

        const postResponse = await request(multiMethodApp).post('/multi');
        expect(postResponse.status).toBe(200);

        // Unallowed methods should return 405
        const putResponse = await request(multiMethodApp).put('/multi');
        expect(putResponse.status).toBe(405);
        expect(putResponse.headers.allow).toBe('GET, POST');
    });
});
